14  Interactive Networks Visualisations

One final element to visualisation is the engagement that they can generate. By engagement, I refer to the attraction of a visualisation that can manifest itself as an experience that people can have with your visuals. Attractive or fun visualisations can draw people in and encourage them to learn more. One method of this attraction can be generated through interactivity. Next, we will cover dynamic visualisation, here, we are talking about interaction.

So far, we have worked only on static visualisations but there are other ways you can present network data that are a little more fun and that can be more instructive. In this chapter we work on two interactive methods and discuss the utility of both. There are multiple packages in R that help you put together interactive visualisations. In this chapter, we will cover two, the visnetwork and threejs packages.

LEARNING ELEMENTS - Data Practices
  • Assessing Data Communication. Sometimes an interaction with data can be very engaging. Rather than just looking at a plot, people can participate in a visualisation.
library(igraph)
library(ADAPTSNA)
library(dplyr) 
library(htmlwidgets) # this helps us work with widgets in markdown
library(htmltools) #this allows the widgets to present in the markdown file
library(visNetwork) # This is the first interactive network package
library(threejs) # This is the second interactive network package

Interactive networks using visNetwork

First, we will be using the visNetwork to create a network visualisation that you can click on, move and view labels one at a time. To do this, we are continuing our visual exploration of our Grime network. For this network, we will pull in both the edge and vertex files. Once we have those in, we need to do a little cleaning of both the edges (nor more selfloops) and then change the names of some of the variables for so the package knows what it is pulling and from where.

vertices.df <- load_data("GRIME_2008_Nodes.csv", header = TRUE) 
edges.df <- load_data("GRIME_2008_Edge.csv", header = TRUE)

edges.df <- edges.df %>%
  filter(collab_weight > 0) ## this cleans the self loops

In the last chapter we worked with these datasets, but let’s take aother look at these objects so you can see how these data are structured. You will see that the vertices.df object has a few node characteristics that help describe those in the network. The edges.df object contains the connections between the nodes in the network and some information about those connections. These will all come into play as we construct our interactive networks.

head(vertices.df)
           name   role female genre_cats cat_span first_release songs_no_
1       Asher D Artist      0          2        1          1988         0
2 Dizzee Rascal Artist      0          5        1          2003         0
3 Lethal Bizzle Artist      0          2        1          2004         0
4         Wiley Artist      0          4        1          2004        45
5   Treble Clef     DJ      0          1        0          2004         0
6       Shystie Artist      1          2        1          2004         0
  charted
1       1
2       1
3       1
4       1
5       0
6       1
head(edges.df)
       featuring host_profile collab_weight
1        Asher D        Wiley             1
2       Scorcher        Wiley             4
3    Bless Beats        Wiley             1
4        Flowdan        Wiley             3
5 Tinchy Stryder        Wiley             2
6         Frisco        Wiley             1

The visNetwork package requires that our each node has a unique ID. This ID is not separate from the network (i.e. a row number in a dataframe), rather, this unique ID MUST MATCH the names of the vertices. THIS IS IMPORTAT. If you are to create this type of network, you will need both the edge information and the node information. The node information, can simply consist of just an id column. So, if you are working with a network that only has information about the edges, you can build a node level dataframe with just the names of the nodes as the ID.

In our case, we have a network that has both of these separate dataframes so we can go straight to our interactive network. Beofre we do, we use the rename() function from the dplyr package to rename the column ‘name’ to id. The visNetwork package can now detect the unique ids that define each node. Then we switch the names of the edgelist to reflect the traditional “from” and “to” that this package requires.

vertices.df <- vertices.df %>%
  rename(id = name)

edges.df <- edges.df %>%
  rename(from = featuring, to = host_profile)

Now that our data is structured in the correct format, we can use the visNetwork() argument to create our interactive network! Outside of a markdown file, if you are working in a script, this will appear in the viewer window of your Rstudio. Here, in a markdown file, it will appear in a widget below the code chunk. Play around with the network to get a sense of how this package renders your visualusation. You can scroll in and out. Select and move a node around in the network. The node you click on will also highlight so you know what node you are looking at.

visNetwork(vertices.df, edges.df)

There is so much more that you can be doing to enhance this visualisation, however. Below, we create more options and set some new variables such as the labels, the title, and shadow options. The label does what you expect, it labels the nodes with their names. Title is an option that enables you to click on or hover over the node and get more information about it. Shadow shows a small shadow behind the node - you can set this as TRUE or FALSE.

Below, I set the label as the id. To do this, we have to ensure that R recognises these as strings or characters. Hence we use the “as.character()” function. Then, we set the title of the node to reflect the node’s gender. Then, for fun, I like the shadows!! Notice that we are directly adding these variables to the dataframe, this is because the package we are using recognises these variables and will automatically pull them into your vis.

vertices.df$label <- as.character(vertices.df$id)

vertices.df$title <- ifelse(vertices.df$female == 1, "F", "M")

vertices.df$shadow <- TRUE

head(vertices.df)
             id   role female genre_cats cat_span first_release songs_no_
1       Asher D Artist      0          2        1          1988         0
2 Dizzee Rascal Artist      0          5        1          2003         0
3 Lethal Bizzle Artist      0          2        1          2004         0
4         Wiley Artist      0          4        1          2004        45
5   Treble Clef     DJ      0          1        0          2004         0
6       Shystie Artist      1          2        1          2004         0
  charted         label title shadow
1       1       Asher D     M   TRUE
2       1 Dizzee Rascal     M   TRUE
3       1 Lethal Bizzle     M   TRUE
4       1         Wiley     M   TRUE
5       0   Treble Clef     M   TRUE
6       1       Shystie     F   TRUE

The object now has these columns in it. Now when we visualise it, we see there are shadows around the nodes (just a cool effect), when you scroll in you will see the labels and as you hover over a node you will see if they are male or female. We have added a few other options to the visualisation. The width = 100% ensures that the visualisation fills the space in the widget. The height option also does something similar. The background, main, submain, and footer options show other ways you can alter the visualisation. Fun, right??

visNetwork(vertices.df, edges.df, 
           background="firebrick",
           main="TITLE HERE", 
           submain="SUB HERE!")

One final thing that we can do is change the colours of the nodes to represent the communities they are a part of. We will cover this a little bit later on. But, just to demonstrate the extent of advanced visualisation, let’s take a quick look here.

To do this, we can create a igraph object from both data frames, run a clustering detection algorithm (louvain) to identify sub groups in Grime 2008. To get this to visualise, we designate the “group” characteristic of the vertices data frame using the membership from the clustering object.

In addition to this nifty visualisation, we have changed a few more options to demonstrate them. First, we have added a node selector dropdown list which you can click on to isolate the ego network of nodes you specify. We have also turned the physics off which removes the network’s springiness allowing you to place the nodes wherever you want them. This might leave some nodes on top of each other. If so, simply click on them and drag them elsewhere.

edges <- graph_from_data_frame(d = edges.df, 
                               vertices = vertices.df, directed = F)

clust <- cluster_louvain(edges)

vertices.df$group <- as.factor(clust$membership)


visNetwork(vertices.df, edges.df)%>%
  visOptions(highlightNearest = TRUE, 
             nodesIdSelection = TRUE) %>%
  visPhysics(enabled = FALSE)

Hopefully your mind is now full of cool ways you can use this style of network vis. If you thought the visNetwork visualisation was cool… wait till you see these ones!!

3D interctive networks with threejs

The second package, threejs, that we are having a look at creates some slightly different interactive visualisations. For this one, you need to start with a network object created in igraph and convert them into a 3D graph. For this chapter, we can use the “edges” igraph object that we created earlier (see above in this chapter).

Since the network object is already there and in the environment (assuming you have run the above chunks), the process to get going is very simple. The function we need to use is the “graphjs()” that will convert your network into a 3D interactive network that looks a bit like a molecular or planetary model. You should be able to do this with any one-mode network (two mode networks will work too, you just need to change colours etc. - more on this later). In this chunk I create an object that has the 3D network called grime_08_3d. Then, we visualise it.

grime_08_3d <- graphjs(edges)

grime_08_3d

Okay, this is very fun, but we can tell a bit more of a story here. Like all of these packages, there are many things that we can do to clean and tell some stories. Here let’s repeat some skills we learned earlier highlighting highly central nodes in this network by changing their colour (let’s say a degree above 3).

Once again, the package threejs looks for specific characteristics of your network to visualise. One of these is the characteristic “color”. The chunk below uses the “set_vertex_attr()” function from igraph to create an attribute that threejs can recognise. We also set the size of the node here to further its readability. The package threejs recognises the option ‘size’ as being the size of the node in the visualisation. Finally, we can set it so hovering over a node reveals the name of the node by using the “vertex.label” option.

grime_colour <- edges

grime_colour <- set_vertex_attr(edges, "color",
                                value = ifelse(degree(edges)> 3, 
                                               "red", "ivory"))

V(grime_colour)$size <- 5

grime_3d_col <- graphjs(grime_colour, 
                                main="Major Collaborators in Grime 2008",
                                bg = "black", 
                                vertex.label = V(grime_colour)$name)

grime_3d_col

If you would like to save this widget, you can do so using the “savewidget()” function from the htmltools package. Then you can call upon it using the “browseURL()” function. However, in order to make this work well in a html format, you will need to use the “browsable()” function on the object. The chunk below should open an html page in your browser with your network for you to present. It will also save the file “grime_2008_js.html” to your set working directory.

grime_3d_col <- browsable(grime_3d_col)

saveWidget(grime_3d_col, 
           file="grime_2008_JS.html")

browseURL("grime_2008_JS.html")

Finally, you can further represent elements of your graph in the 3D network. For example, you can change the colours of the nodes to reflect the membership of which community they are in. In this chunk, I use the infomap community detection algorithm to identify which communities the nodes are in. Then, I create a new node level characteristic called “color” that captures which community they are in. If you have many communities, you may need to use a colour palette package like vidris or RColorBrewer,

grime_coms <- edges

cl <- cluster_infomap(grime_coms)

V(grime_coms)$color <- cl$membership

V(grime_coms)$size <- 5

grime_coms3D <- graphjs(grime_coms, 
                        edge.color = "maroon",  
                        bg = "white", 
                        main = "Communities in Grime 2008")

grime_coms3D

Closing Thoughts on Interactive Networks

I think these networks are cool. However, you must be thoughtful about use-cases for them. If you are an academic, you may think these are a bit of a gimmick! They only really work in online spaces while are completely useless in print. The click functions and maneuverable attributes of these graphs are fun to play around with and are useful in grabbing the imagination of readers online or in an interactive exhibition. However, in many academic uses for network analysis, it is much easier to present static graphs. Still… they are loads of fun, and you can waste a lot of time playing around with these!

Summary

Here you have learned how to create interactive visualisations. Specifically, you have learned how to create two types: interactive and 3D.